package com.yb.guigu.pick.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yb.guigu.pick.auth.bean.dto.response.SysPermissionDTO;
import com.yb.guigu.pick.auth.bean.dto.response.SysRolePermissionDTO;
import com.yb.guigu.pick.auth.bean.dto.response.SysRouteDTO;
import com.yb.guigu.pick.auth.bean.vo.request.SysRolePermissionAssignVo;
import com.yb.guigu.pick.auth.entity.*;
import com.yb.guigu.pick.auth.mapper.*;
import com.yb.guigu.pick.auth.service.ISysPermissionService;
import com.yb.guigu.pick.auth.service.ISysRolePermissionService;
import com.yb.guigu.pick.auth.service.ISysRoleRouteService;
import com.yb.guigu.pick.auth.service.ISysRoleService;
import com.yb.guigu.pick.core.bean.GuiguResult;
import com.yb.guigu.pick.core.exception.GuiguBusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 姚兵
 * @since 2023-05-30
 */
@Service
@Slf4j
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Autowired
    ISysPermissionService sysPermissionService;


    @Autowired
    ISysRolePermissionService sysRolePermissionService;


    @Autowired
    SysRouteMapper sysRouteMapper;

    @Autowired
    ISysRoleRouteService sysRoleRouteService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public GuiguResult assignPermission(Integer roleId, SysRolePermissionAssignVo rolePermissionAssignVo) {

        //查询已有权限
        List<SysRolePermission> permissionAssigned = sysRolePermissionService
                .list(new LambdaQueryWrapper<SysRolePermission>()
                .eq(SysRolePermission::getRoleId, roleId)
                .select(SysRolePermission::getId,SysRolePermission::getPermissionId));

        List<Integer> permissionIds=new ArrayList<>();

        //获取所有已有权限的permissionId
        if(!CollectionUtils.isEmpty(permissionAssigned)){
            permissionIds=permissionAssigned.stream().map(SysRolePermission::getPermissionId).collect(Collectors.toList());
        }

        //获取新增权限
        List<Integer> toAssignedPermissionIds = rolePermissionAssignVo.getPermissionIds();

        //数据过滤掉已经分配的权限
        toAssignedPermissionIds.removeAll(permissionIds);

        if(CollectionUtils.isEmpty(toAssignedPermissionIds)){
            GuiguBusinessException.cast("权限列表不能为空");
        }

        //保存记录结果
        List<SysPermission> sysPermissions = sysPermissionService
                .list(new LambdaQueryWrapper<SysPermission>()
                .in(SysPermission::getPermissionId,toAssignedPermissionIds)
                                .select(SysPermission::getId,SysPermission::getPermissionId)
                );

        assignPermission(roleId,sysPermissions);
        //先删除已有权限，在添加新的权限

        return GuiguResult.success();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public GuiguResult unAssignPermission(Integer roleId, SysRolePermissionAssignVo rolePermissionAssignVo) {
        List<Integer> permissionIds = rolePermissionAssignVo.getPermissionIds();

        if(CollectionUtils.isEmpty(permissionIds)){
            return GuiguResult.success();
        }

        sysRolePermissionService.remove(
                new LambdaQueryWrapper<SysRolePermission>()
                        .eq(SysRolePermission::getRoleId,roleId)
                        .in(SysRolePermission::getPermissionId,permissionIds)
        );
        return GuiguResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public GuiguResult unAssignRoute(Integer roleId, SysRolePermissionAssignVo rolePermissionAssignVo) {
        List<Integer> routeIds = rolePermissionAssignVo.getRouteIds();

        if(CollectionUtils.isEmpty(routeIds)){
            return GuiguResult.success();
        }

        sysRoleRouteService.remove(
                new LambdaQueryWrapper<SysRoleRoute>()
                        .eq(SysRoleRoute::getRoleId,roleId)
                        .in(SysRoleRoute::getRouteId,routeIds)
        );
        return GuiguResult.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public GuiguResult assignRoute(Integer roleId, SysRolePermissionAssignVo rolePermissionAssignVo) {

        //查询已有权限
        List<SysRoleRoute> routeAssigned = sysRoleRouteService
                .list(new LambdaQueryWrapper<SysRoleRoute>()
                        .eq(SysRoleRoute::getRoleId, roleId)
                        .select(SysRoleRoute::getRouteId));

        List<Integer> routeIds=new ArrayList<>();

        //获取所有已有权限的permissionId
        if(!CollectionUtils.isEmpty(routeAssigned)){
            routeIds=routeAssigned.stream().map(SysRoleRoute::getRouteId).collect(Collectors.toList());
        }

        //获取新增权限
        List<Integer> toAssignedRouteIds = rolePermissionAssignVo.getRouteIds();

        //数据过滤掉已经分配的权限
        toAssignedRouteIds.removeAll(routeIds);

        if(CollectionUtils.isEmpty(toAssignedRouteIds)){
            GuiguBusinessException.cast("路由列表不能为空");
        }

        //保存记录结果
        List<SysRoute> sysRoutes = sysRouteMapper
                .selectList(new LambdaQueryWrapper<SysRoute>()
                        .in(SysRoute::getId,toAssignedRouteIds)
                        .select(SysRoute::getId,SysRoute::getRouteIdPath)
                );

        assignRoutes(roleId,sysRoutes);
        //先删除已有权限，在添加新的权限

        return GuiguResult.success();
    }



    @Override
    public GuiguResult roleRoute(Integer roleId) {
        return null;
    }

    @Override
    public GuiguResult rolePermission(Integer roleId) {

        List<SysPermission> allPermissions = sysPermissionService.list();


        List<SysRolePermission> rolePermissions = sysRolePermissionService.list(new LambdaQueryWrapper<SysRolePermission>().eq(SysRolePermission::getRoleId, roleId));


        List<SysPermissionDTO> permissionAssigned=new ArrayList<>();

        List<SysPermissionDTO> permissionUnAssigned=new ArrayList<>();

        allPermissions.forEach(permission->{
            SysPermissionDTO sysPermissionDTO=new SysPermissionDTO();
            BeanUtils.copyProperties(permission,sysPermissionDTO);

            Optional<SysRolePermission> optional = rolePermissions
                    .stream()
                    .filter(rolePermission ->
                            rolePermission.getPermissionId()
                                    .equals(permission.getPermissionId()))
                    .findFirst();
            if(optional.isPresent()){
                permissionAssigned.add(sysPermissionDTO);
            }else{
                permissionUnAssigned.add(sysPermissionDTO);
            }
        });


        SysRolePermissionDTO sysRolePermissionDTO = new SysRolePermissionDTO();



        sysRolePermissionDTO.setRoleId(roleId);
        sysRolePermissionDTO.setPermissionAssigned(permissionAssigned);
        sysRolePermissionDTO.setPermissionUnAssigned(permissionUnAssigned);
        return GuiguResult.success(sysRolePermissionDTO);
    }

    @Override
    public GuiguResult roleRoutes(Integer roleId) {


        List<SysRoute> allRoutes = sysRouteMapper.selectList(null);


        List<SysRoleRoute> roleRoutes = sysRoleRouteService.list(new LambdaQueryWrapper<SysRoleRoute>().eq(SysRoleRoute::getRoleId, roleId));



        List<SysRouteDTO> routeAssigned=new ArrayList<>();

        List<SysRouteDTO> routeUnAssigned=new ArrayList<>();

        allRoutes.forEach(route -> {

            SysRouteDTO sysRouteDTO=new SysRouteDTO();
            BeanUtils.copyProperties(route,sysRouteDTO);

            Optional<SysRoleRoute> optional = roleRoutes.stream().
                    filter(roleRoute -> roleRoute.getRouteId().equals(route.getId()))
                    .findFirst();
            if(optional.isPresent()){
                routeAssigned.add(sysRouteDTO);
            }else{
                routeUnAssigned.add(sysRouteDTO);
            }
        });

        SysRolePermissionDTO sysRolePermissionDTO = new SysRolePermissionDTO();


        sysRolePermissionDTO.setRoleId(roleId);
        sysRolePermissionDTO.setRouteAssigned(routeAssigned);
        sysRolePermissionDTO.setRouteUnAssigned(routeUnAssigned);
        return GuiguResult.success(sysRolePermissionDTO);
    }



    private void assignPermission(Integer roleId,List<SysPermission> sysPermissions){
        if(CollectionUtils.isEmpty(sysPermissions)){
            return;
        }
        List<SysRolePermission> list = sysPermissions.stream().map(sysPermission -> {
            SysRolePermission sysRolePermission = new SysRolePermission();
            sysRolePermission.setPermissionId(sysPermission.getPermissionId());
            sysRolePermission.setRoleId(roleId);
            sysRolePermission.setCreateTime(LocalDateTime.now());
            return sysRolePermission;
        }).collect(Collectors.toList());

        sysRolePermissionService.saveBatch(list);
    }
    private void assignRoutes(Integer roleId,List<SysRoute> sysRoutes){
        if(CollectionUtils.isEmpty(sysRoutes)){
            return;
        }

        List<SysRoleRoute> listToInsert = sysRoutes.stream().map(item -> {
            SysRoleRoute sysRoleRoute = new SysRoleRoute();
            sysRoleRoute.setRoleId(roleId);
            sysRoleRoute.setRouteIdPath(item.getRouteIdPath());
            sysRoleRoute.setRouteId(item.getId());
            sysRoleRoute.setCreateTime(LocalDateTime.now());
            return sysRoleRoute;
        }).collect(Collectors.toList());


        sysRoleRouteService.saveBatch(listToInsert);
    }
}
